﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Vortex.SceneFramework.CSS {

	/// <summary>
	/// Represents a collection of indexed style property values.
	/// Each of value has also a importance parameter which defines a weight of style value during style computation.
	/// </summary>
	public class StyleValueSet {
		protected StyleValue[] _values = StyleSheet.CreateDefaultValueArray();

		/// <summary>
		/// Initializes a new instance of the <see cref="StyleValueSet"/> class.
		/// </summary>
		public StyleValueSet() {
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="StyleValueSet"/> class from another instance with copying all of styles.
		/// </summary>
		/// <param name="source">The source for value copying.</param>
		public StyleValueSet (StyleValueSet source) {
			if (source == null) throw new ArgumentNullException("source");

			_values = (StyleValue[])source._values.Clone();
		}

		#region Value Access

		/// <summary>
		/// Gets or sets the style value for the specified style property index.
		/// </summary>
		/// <value>Instance of style value or null if no value</value>
		public StyleValue this[StyleKey property] {
			get {
				if (null == property) throw new ArgumentNullException("property");
				return _values[property.Index];
			}
			set {
				if (null == property) throw new ArgumentNullException("property");
				_values[property.Index] = value;
			}
		}

		/// <summary>
		/// Gets or sets the style value for the specified style property index.
		/// </summary>
		/// <value>Instance of style value or null if no value</value>
		public StyleValue this[int propertyIndex] {
			get {
				if (propertyIndex < 0 || propertyIndex >= StyleSheet.PropertyCount) throw new ArgumentOutOfRangeException("propertyIndex");
				return _values[propertyIndex];
			}
			set {
				if (propertyIndex < 0 || propertyIndex >= StyleSheet.PropertyCount) throw new ArgumentOutOfRangeException("propertyIndex");
				_values[propertyIndex] = value;
			}
		}

		/// <summary>
		/// Clears the value set. Empties all of values.
		/// </summary>
		public void Clear() {
			for (int n = 0; n < _values.Length; ++n) {
				//set default value with lowest importance
				_values[n] = new StyleValue(StyleSheet.GetPropertyInfo(n).DefaultValue, StyleValue.DEFAULT_IMPORTANCE);
			}
		}

		#endregion

		/// <summary>
		/// Merge specified value set with current one leaving most important values.
		/// </summary>
		/// <param name="source">Source value set to merge with this one.</param>
		public void Merge(StyleValueSet source) {
			if (null == source) throw new ArgumentNullException("source");

			StyleValue[] values = source._values;

			//iterate over all of values and leave most important only
			for (int n = 0; n < _values.Length; ++n) {
				if (values[n].Importance > _values[n].Importance) {
					_values[n] = values[n];
				}
			}
		}

		/// <summary>
		/// Copies all of style values from the specified collection into this one.
		/// </summary>
		/// <param name="source">The source collection to copy values from.</param>
		public void Copy(StyleValueSet source) {
			if (null == source) throw new ArgumentNullException("source");

			Array.Copy(source._values, _values, _values.Length);
		}
	}

}
